package com.haojiang.mh.widget.chart;

import android.content.Context;
import android.graphics.*;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.view.View;
import androidx.annotation.Nullable;
import com.haojiang.mh.R;
import com.haojiang.mh.service.entity.SleepCycleChartBean;
import com.haojiang.mh.service.entity.SleepDurationBean;
import com.haojiang.mh.utils.MUtil;
import com.haojiang.mh.utils.SizeUtil;

import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 渐变背景+间断矩形柱
 * 现用在《月报--睡眠周期分布》
 */
public class MonthSleepCycleChartView extends View {

    private TextPaint textPaint;//文字画笔
    //坐标刻度、背景、柱子 画笔
    private Paint coordinatePaint, bgPaint, columnPaint;
    private int width, height, defaultWidth, defaultHeight;//当前View宽高、默认宽高
    private float xItemWidth, yItemHeight; //X轴间隔块宽度、Y轴间隔块高度
    //X轴高度、X轴文字高度、Y轴宽度、Y轴文字高度
    private int xAxisHeight, xAxisTextHeight, yAxisWidth, yAxisTextHeight;
    private int drawHeight, columnHeight, axisPadding; //绘制高度、柱子高度、坐标轴间距
    //通用、周日、深睡眠、浅睡眠、rem、清醒 颜色值
    private int commonColor, sundayColor, deepColor, lightColor, remColor, awakeColor;
    private int bgGraLeftColor, bgGraRightColor;//背景渐变顶部、底部色值
    private LinearGradient shader;//线性渐变
    private RectF rectF = new RectF();//矩形
    private int xAxisTextSize, yAxisTextSize;//X轴文字、Y轴文字大小
    private List<SleepCycleChartBean> beanList;
    private int hourNum = 18;

    public MonthSleepCycleChartView(Context context) {
        this(context, null);
    }

    public MonthSleepCycleChartView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public MonthSleepCycleChartView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        xAxisHeight = SizeUtil.dp2px(context, 3);
        xAxisTextHeight = SizeUtil.dp2px(context, 30);
        yAxisWidth = SizeUtil.dp2px(context, 30);
        yAxisTextHeight = SizeUtil.dp2px(context, 20);
        drawHeight = SizeUtil.dp2px(context, 250);
        axisPadding = SizeUtil.dp2px(context, 10);
        columnHeight = SizeUtil.dp2px(context, 3);

        defaultWidth = SizeUtil.dp2px(context, 340);
        defaultHeight = axisPadding + drawHeight + axisPadding + xAxisHeight + xAxisTextHeight;

//        commonColor = getResources().getColor(R.color.white_half);
//        sundayColor = getResources().getColor(R.color.purple_3);
//        deepColor = getResources().getColor(R.color.purple_4);
//        lightColor = getResources().getColor(R.color.purple_3);
//        remColor = getResources().getColor(R.color.purple_2);
//        awakeColor = getResources().getColor(R.color.grey_3);
        commonColor = getResources().getColor(R.color.white_half);
        sundayColor = getResources().getColor(R.color.color_golden_dark_n);
        deepColor = getResources().getColor(R.color.deepColor);         //深睡眠颜色
        lightColor = getResources().getColor(R.color.lightColor);             //浅睡眠颜色
        remColor = getResources().getColor(R.color.remColor);               //动眼睡眠颜色
        awakeColor = getResources().getColor(R.color.awakeColor);               //清醒颜色
        bgGraRightColor = getResources().getColor(R.color.white) & 0x00FFFFFF;
        bgGraLeftColor = getResources().getColor(R.color.white) & 0x19FFFFFF;

        xAxisTextSize = SizeUtil.sp2px(context, 10);
        yAxisTextSize = SizeUtil.sp2px(context, 12);

        textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
        textPaint.setTextAlign(Paint.Align.CENTER);
        textPaint.setColor(commonColor);

        coordinatePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        coordinatePaint.setStyle(Paint.Style.FILL);
        coordinatePaint.setColor(commonColor);

        columnPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        columnPaint.setStyle(Paint.Style.FILL);

        bgPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        bgPaint.setStyle(Paint.Style.FILL);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        width = w;
        height = h;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        if (beanList == null || beanList.isEmpty()) return;

        xItemWidth = (float) (width - yAxisWidth - axisPadding * 2) / hourNum;
        yItemHeight = (float) drawHeight / (beanList.size() - 1);

        drawXAxis(canvas);

        drawYAxis(canvas);

        drawBackGround(canvas);

        drawColumn(canvas);
    }

    /**
     * 绘制X轴
     */
    private void drawXAxis(Canvas canvas) {
        textPaint.setTextSize(xAxisTextSize);
        for (int i = 0; i <= hourNum; i++) {
            if (i % 2 != 0) continue;
            canvas.drawLine(
                    yAxisWidth + axisPadding + xItemWidth * i,
                    height - xAxisTextHeight - xAxisHeight,
                    yAxisWidth + axisPadding + xItemWidth * i,
                    height - xAxisTextHeight,
                    coordinatePaint
            );
            canvas.drawText(
                    i + "h",
                    yAxisWidth + axisPadding + xItemWidth * i,
                    SizeUtil.getBaseLine(textPaint, height, xAxisTextHeight),
                    textPaint
            );
        }
    }

    /**
     * 绘制Y轴
     */
    private void drawYAxis(Canvas canvas) {
        textPaint.setTextSize(yAxisTextSize);
        for (int i = 0; i <= (beanList.size() - 1) / 7; i++) {
            SleepCycleChartBean bean = beanList.get(i * 7);
            textPaint.setColor(bean.isCurrMonth() ? sundayColor : commonColor);
            canvas.drawText(
                    bean.getDay(),
                    yAxisWidth * 0.5f,
                    SizeUtil.getBaseLine(textPaint, axisPadding + yItemHeight * 7 * i + yAxisTextHeight * 0.5f, yAxisTextHeight),
                    textPaint
            );
            canvas.drawCircle(yAxisWidth, axisPadding + yItemHeight * 7 * i, 5, coordinatePaint);
        }
    }

    /**
     * 绘制间隔渐变背景
     */
    private void drawBackGround(Canvas canvas) {
        for (int i = 0; i < (beanList.size() - 1) / 7; i++) {
            if (i % 2 != 0) continue;
            float left = yAxisWidth + axisPadding;
            float top = axisPadding + yItemHeight * 7 * i;
            float right = width - axisPadding;
            float bottom = top + yItemHeight * 7;
            shader = new LinearGradient(left, 0, right, 0, bgGraLeftColor, bgGraRightColor, Shader.TileMode.CLAMP);
            bgPaint.setShader(shader);
            canvas.drawRect(left, top, right, bottom, bgPaint);
        }
    }

    /**
     * 绘制柱状图
     */
    private void drawColumn(Canvas canvas) {
        int totalMinute = hourNum * 60;
        int drawWidth = width - yAxisWidth - axisPadding * 2;
        for (int i = 0; i < beanList.size(); i++) {
            SleepCycleChartBean bean = beanList.get(i);
            if (bean == null || bean.getLine() == null || bean.getLine().isNull()) continue;
            SleepDurationBean sdb = bean.getLine();
            //深睡眠
            float deepRight = yAxisWidth + axisPadding + sdb.getDeep_duration_minute() * drawWidth / totalMinute;
            rectF.set(
                    yAxisWidth + axisPadding,
                    axisPadding + yItemHeight * i - columnHeight * 0.5f,
                    deepRight,
                    axisPadding + yItemHeight * i + columnHeight * 0.5f
            );
            columnPaint.setColor(deepColor);
            canvas.drawRect(rectF, columnPaint);
            //浅睡眠
            float lightRight = deepRight + sdb.getLight_duration_minute() * drawWidth * 1.0f / totalMinute;
            rectF.set(
                    deepRight,
                    axisPadding + yItemHeight * i - columnHeight * 0.5f,
                    lightRight,
                    axisPadding + yItemHeight * i + columnHeight * 0.5f
            );
            columnPaint.setColor(lightColor);
            canvas.drawRect(rectF, columnPaint);
            //REM
            float remRight = lightRight + sdb.getRem_duration_minute() * drawWidth * 1.0f / totalMinute;
            rectF.set(
                    lightRight,
                    axisPadding + yItemHeight * i - columnHeight * 0.5f,
                    remRight,
                    axisPadding + yItemHeight * i + columnHeight * 0.5f
            );
            columnPaint.setColor(remColor);
            canvas.drawRect(rectF, columnPaint);
            //清醒
            float awakeRight = remRight + sdb.getAwake_duration_minute() * drawWidth * 1.0f / totalMinute;
            if (awakeRight > (yAxisWidth + axisPadding + drawWidth)) {
                awakeRight = yAxisWidth + axisPadding + drawWidth;
            }
            rectF.set(
                    remRight,
                    axisPadding + yItemHeight * i - columnHeight * 0.5f,
                    awakeRight,
                    axisPadding + yItemHeight * i + columnHeight * 0.5f
            );
            columnPaint.setColor(awakeColor);
            canvas.drawRect(rectF, columnPaint);
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        setMeasuredDimension(
                getMeasuredLength(widthMeasureSpec, true),
                getMeasuredLength(heightMeasureSpec, false)
        );
    }

    private int getMeasuredLength(int length, boolean isWidth) {
        int specMode = MeasureSpec.getMode(length);
        int specSize = MeasureSpec.getSize(length);
        int size;
        int padding = isWidth ? getPaddingLeft() + getPaddingRight() : getPaddingTop() + getPaddingBottom();
        if (specMode == MeasureSpec.EXACTLY) {
            size = specSize;
        } else if (specMode == MeasureSpec.UNSPECIFIED) {
            size = isWidth ? defaultWidth : defaultHeight;
        } else {
            size = isWidth ? padding + defaultWidth : padding + defaultHeight;
            if (specMode == MeasureSpec.AT_MOST) {
                size = Math.min(size, specSize);
            }
        }
        return size;
    }

    public void setChartData(List<SleepCycleChartBean> data) {
        if (beanList == null) beanList = new ArrayList<>();
        beanList.clear();
        int max = 0;
        if (data != null && !data.isEmpty()) {
            beanList.addAll(data);
            for (int i = 0; i < beanList.size(); i++) {
                SleepCycleChartBean bean = beanList.get(i);
                SleepDurationBean line = bean.getLine();
                max = Math.max(max, line.getDeep_duration_minute() + line.getAwake_duration_minute() + line.getLight_duration_minute() + line.getRem_duration_minute());
                if (max > 60 * 18) {
                    break;
                }
            }
            if (max > 60 * 18) {
                hourNum = 24;
            } else {
                hourNum = 18;
            }
            getCompleteMonthData();
        }
        invalidate();
    }

    /**
     * 获取完整月份（包含前后月的周末）数据
     */
    private void getCompleteMonthData() {
        int[] ymd = MUtil.INSTANCE.getYearMonthDay(beanList.get(0).getDate());
        Calendar cal = Calendar.getInstance();
        cal.set(ymd[0], ymd[1] - 1, ymd[2]);

        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault());
        while (cal.get(Calendar.DAY_OF_WEEK) != Calendar.SUNDAY) {
            cal.add(Calendar.DAY_OF_MONTH, -1);
            addBeanList(simpleDateFormat.format(new Date(cal.getTimeInMillis())), true);
        }
        cal.set(ymd[0], ymd[1], ymd[2]);
        while (cal.get(Calendar.DAY_OF_WEEK) != Calendar.SUNDAY) {
            addBeanList(simpleDateFormat.format(new Date(cal.getTimeInMillis())), false);
            cal.add(Calendar.DAY_OF_MONTH, 1);
        }
        addBeanList(simpleDateFormat.format(new Date(cal.getTimeInMillis())), false);
    }

    /**
     * 添加Bean
     */
    private void addBeanList(String date, boolean isBefore) {
        SleepCycleChartBean bean = new SleepCycleChartBean();
        bean.setDate(date);
        bean.setCurrMonth(false);
        if (isBefore) {
            beanList.add(0, bean);
        } else {
            beanList.add(bean);
        }
    }
}

